package com.smartcampusbackend.service.impl;

import com.smartcampusbackend.model.AcademicWarning;
import com.smartcampusbackend.model.GraduationApplication;
import com.smartcampusbackend.model.User;
import com.smartcampusbackend.model.OperationLog;
import com.smartcampusbackend.mapper.GraduationApplicationMapper;
import com.smartcampusbackend.mapper.UserMapper;
import com.smartcampusbackend.service.AcademicWarningService;
import com.smartcampusbackend.service.GradeService;
import com.smartcampusbackend.service.GraduationService;
import com.smartcampusbackend.service.OperationLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class GraduationServiceImpl implements GraduationService {
    private static final Logger logger = LoggerFactory.getLogger(GraduationServiceImpl.class);
    
    @Autowired
    private GraduationApplicationMapper graduationApplicationMapper;
    
    @Autowired
    private AcademicWarningService academicWarningService;
    
    @Autowired
    private GradeService gradeService;
    
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private OperationLogService operationLogService;

    @Override
    @Transactional
    public String applyForGraduation(GraduationApplication application) {
        logger.info("提交毕业申请，studentId: {}", application.getStudentId());
        GraduationApplication existingApplication = checkGraduationStatus(application.getStudentId());
        if (existingApplication != null && 
            ("PENDING".equals(existingApplication.getStatus()) || "APPROVED".equals(existingApplication.getStatus()))) {
            return "您已有一个进行中的毕业申请，请勿重复提交";
        }
        List<AcademicWarning> activeWarnings = academicWarningService.listStudentWarnings(application.getStudentId())
            .stream()
            .filter(warning -> "ACTIVE".equals(warning.getStatus()))
            .collect(Collectors.toList());
        boolean hasWarnings = !activeWarnings.isEmpty();
        application.setIsWarningResolved(!hasWarnings);
        if (hasWarnings) {
            StringBuilder warningMsg = new StringBuilder("您有未解决的学业预警，请在毕业前进行补考！\n涉及科目：");
            for (int i = 0; i < activeWarnings.size(); i++) {
                AcademicWarning warning = activeWarnings.get(i);
                warningMsg.append(warning.getCourseName());
                if (i < activeWarnings.size() - 1) {
                    warningMsg.append("、");
                }
            }
            logger.info("学生{}申请毕业被拒绝，原因：有{}条未解决的学业预警", 
                       application.getStudentId(), activeWarnings.size());
            return warningMsg.toString();
        }
        application.setStatus("PENDING");
        application.setApplicationDate(LocalDateTime.now());
        application.setCreateTime(LocalDateTime.now());
        application.setUpdateTime(LocalDateTime.now());
        graduationApplicationMapper.insert(application);
        // 日志记录
        User student = userMapper.selectById(application.getStudentId());
        OperationLog log = new OperationLog();
        log.setBusinessType("毕业申请");
        log.setBusinessId(String.valueOf(application.getId()));
        log.setOperationType("提交申请");
        log.setOperatorId(String.valueOf(application.getStudentId()));
        log.setOperatorName(student != null ? (student.getRealName() != null ? student.getRealName() : student.getUsername()) : "未知");
        log.setOperatorRole("学生");
        log.setContent("学生提交毕业申请");
        log.setStatus("完成");
        log.setIsSignature(false);
        log.setCreateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        operationLogService.addLog(log);
        return "毕业申请提交成功，请等待审核";
    }

    @Override
    public GraduationApplication checkGraduationStatus(Long studentId) {
        logger.info("查询毕业申请状态，studentId: {}", studentId);
        
        return graduationApplicationMapper.selectOne(
            new QueryWrapper<GraduationApplication>()
                .eq("student_id", studentId)
                .orderByDesc("application_date")
                .last("LIMIT 1")
        );
    }

    @Override
    public List<Map<String, Object>> listGraduationApplications(int page, int size) {
        logger.info("查询毕业申请列表，page: {}, size: {}", page, size);
        
        // 计算偏移量
        int offset = (page - 1) * size;
        
        List<GraduationApplication> applications = graduationApplicationMapper.selectList(
            new QueryWrapper<GraduationApplication>()
                .orderByDesc("application_date")
                .last("LIMIT " + offset + ", " + size)
        );
        
        // 转换为包含学生信息的Map列表
        List<Map<String, Object>> result = new ArrayList<>();
        for (GraduationApplication application : applications) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", String.valueOf(application.getId()));
            map.put("studentId", String.valueOf(application.getStudentId()));
            map.put("reviewerId", application.getReviewerId() == null ? null : String.valueOf(application.getReviewerId()));
            map.put("applicationDate", application.getApplicationDate());
            map.put("status", application.getStatus());
            map.put("isCreditSufficient", application.getIsCreditSufficient());
            map.put("isWarningResolved", application.getIsWarningResolved());
            map.put("rejectReason", application.getRejectReason());
            map.put("reviewDate", application.getReviewDate());
            map.put("createTime", application.getCreateTime());
            map.put("updateTime", application.getUpdateTime());
            
            // 添加学生信息
            User student = userMapper.selectById(application.getStudentId());
            if (student != null) {
                map.put("studentName", student.getRealName());
                map.put("studentNumber", student.getUsername());
            } else {
                map.put("studentName", "未知");
                map.put("studentNumber", "未知");
            }
            
            result.add(map);
        }
        
        return result;
    }

    @Override
    @Transactional
    public String approveGraduation(Long applicationId) {
        logger.info("批准毕业申请，applicationId: {}", applicationId);
        GraduationApplication application = graduationApplicationMapper.selectById(applicationId);
        if (application == null) {
            return "毕业申请不存在";
        }
        Map<String, Object> gradeStats = gradeService.getStudentGradeStatistics(application.getStudentId().toString());
        Double totalCredits = gradeStats.get("totalCredits") != null ? 
            Double.parseDouble(gradeStats.get("totalCredits").toString()) : 0.0;
        double requiredCredits = 120.0;
        boolean isCreditSufficient = totalCredits >= requiredCredits;
        application.setIsCreditSufficient(isCreditSufficient);
        if (!isCreditSufficient) {
            return String.format("学分不足，当前已修学分：%.1f，毕业要求学分：%.1f，请选择学分不足拒绝并填写建议。", totalCredits, requiredCredits);
        }
        application.setStatus("APPROVED");
        application.setReviewDate(LocalDateTime.now());
        application.setUpdateTime(LocalDateTime.now());
        graduationApplicationMapper.updateById(application);
        // 日志记录
        User reviewer = application.getReviewerId() != null ? userMapper.selectById(application.getReviewerId()) : null;
        OperationLog log = new OperationLog();
        log.setBusinessType("毕业申请");
        log.setBusinessId(String.valueOf(application.getId()));
        log.setOperationType("审批通过");
        log.setOperatorId(application.getReviewerId() != null ? String.valueOf(application.getReviewerId()) : "0");
        log.setOperatorName(reviewer != null ? (reviewer.getRealName() != null ? reviewer.getRealName() : reviewer.getUsername()) : "管理员");
        log.setOperatorRole("管理员");
        log.setContent("管理员批准毕业申请");
        log.setStatus("完成");
        log.setIsSignature(false);
        log.setCreateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        operationLogService.addLog(log);
        return "毕业申请已批准";
    }

    @Override
    @Transactional
    public String rejectGraduation(Long applicationId, String rejectReason) {
        logger.info("拒绝毕业申请，applicationId: {}, reason: {}", applicationId, rejectReason);
        GraduationApplication application = graduationApplicationMapper.selectById(applicationId);
        if (application == null) {
            return "毕业申请不存在";
        }
        application.setStatus("REJECTED");
        application.setRejectReason(rejectReason);
        application.setReviewDate(LocalDateTime.now());
        application.setUpdateTime(LocalDateTime.now());
        graduationApplicationMapper.updateById(application);
        // 日志记录
        User reviewer = application.getReviewerId() != null ? userMapper.selectById(application.getReviewerId()) : null;
        OperationLog log = new OperationLog();
        log.setBusinessType("毕业申请");
        log.setBusinessId(String.valueOf(application.getId()));
        log.setOperationType("审批拒绝");
        log.setOperatorId(application.getReviewerId() != null ? String.valueOf(application.getReviewerId()) : "0");
        log.setOperatorName(reviewer != null ? (reviewer.getRealName() != null ? reviewer.getRealName() : reviewer.getUsername()) : "管理员");
        log.setOperatorRole("管理员");
        log.setContent("管理员拒绝毕业申请，原因：" + rejectReason);
        log.setStatus("完成");
        log.setIsSignature(false);
        log.setCreateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        operationLogService.addLog(log);
        return "毕业申请已拒绝";
    }
    
    @Override
    @Transactional
    public String rejectGraduationWithCreditInfo(Long applicationId, Map<String, Object> rejectInfo) {
        logger.info("拒绝毕业申请（学分不足），applicationId: {}", applicationId);
        GraduationApplication application = graduationApplicationMapper.selectById(applicationId);
        if (application == null) {
            return "毕业申请不存在";
        }
        StringBuilder reasonBuilder = new StringBuilder("学分不足：\n");
        reasonBuilder.append("专业要求学分：").append(rejectInfo.get("requiredCredits")).append("\n");
        reasonBuilder.append("已修学分：").append(rejectInfo.get("currentCredits")).append("\n");
        reasonBuilder.append("需要补修学分：").append(rejectInfo.get("missingCredits")).append("\n");
        reasonBuilder.append("建议补修：").append(rejectInfo.get("suggestion"));
        application.setStatus("REJECTED");
        application.setRejectReason(reasonBuilder.toString());
        application.setReviewDate(LocalDateTime.now());
        application.setUpdateTime(LocalDateTime.now());
        graduationApplicationMapper.updateById(application);
        // 日志记录
        User reviewer = application.getReviewerId() != null ? userMapper.selectById(application.getReviewerId()) : null;
        OperationLog log = new OperationLog();
        log.setBusinessType("毕业申请");
        log.setBusinessId(String.valueOf(application.getId()));
        log.setOperationType("学分不足拒绝");
        log.setOperatorId(application.getReviewerId() != null ? String.valueOf(application.getReviewerId()) : "0");
        log.setOperatorName(reviewer != null ? (reviewer.getRealName() != null ? reviewer.getRealName() : reviewer.getUsername()) : "管理员");
        log.setOperatorRole("管理员");
        log.setContent("管理员因学分不足拒绝毕业申请，详情：" + reasonBuilder.toString());
        log.setStatus("完成");
        log.setIsSignature(false);
        log.setCreateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        operationLogService.addLog(log);
        return "毕业申请已拒绝";
    }
} 